package it.antonio.ilpizze.reflection;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MethodAccessor {
	private Method method;

	public MethodAccessor(Method method) {
		super();
		if(method == null){
			throw new ReflectionException("method cannot be null");
		}
		this.method = method;
	}

	public Object invoke(Object instance, Object... args) {
		try {
			if(!method.isAccessible()){
				method.setAccessible(true);
			}
			return method.invoke(instance, args);
		} catch (IllegalArgumentException e) {
			throw new ReflectionException(e.getMessage(), e);
		} catch (IllegalAccessException e) {
			throw new ReflectionException(e.getMessage(), e);
		} catch (InvocationTargetException e) {
			if(e.getCause() instanceof RuntimeException){
				throw (RuntimeException)e.getCause();
			}
			throw new ReflectionException(e.getCause().getMessage(), e.getCause());
		}
	}

	public <T extends Annotation> T getAnnotation(Class<T> annotation) {
		return method.getAnnotation(annotation);
	}

	public Annotation[][] getParameterAnnotations() {
		return method.getParameterAnnotations();
	}

	public Class<?> getReturnType() {
		return method.getReturnType();
	}

	public Class<?>[] getParameterTypes() {
		return method.getParameterTypes();
	}

	public Method getOriginalMethod() {
		return method;
	}

	public String getName() {
		return method.getName();
	}

	public boolean isAnnotationPresent(Class<? extends Annotation> annotation) {
		return method.isAnnotationPresent(annotation);
	}
	@Override
	public boolean equals(Object o) {
		if(o instanceof MethodAccessor){
			MethodAccessor m = (MethodAccessor) o;
			return m.method.equals(method);
		}
		if(o instanceof Method){
			Method m = (Method) o;
			return m.equals(method);
		}
		return false;
	}
	@Override
	public String toString() {
		return method.toString();
	}

}